//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "ListBindingSitePrediction.h"
#include "ProcessCathFASTAProfile.h"
#include "Pratt2PatternsByCATH.h"
#include "ProcessBindingFASTAProfile.h"
#include "PredictBindingSiteByPattern.h"
#include "SearchPrositePattern.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <fstream>
#include <iostream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define MAX_SIZE             500000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
namespace BindingSitePrediction {

  bool EqualHeader (TNode <PredictBindingSiteByPattern>* predictBindingSiteByPattern, void* ref) {

    return (!strcmp(predictBindingSiteByPattern->Info()->Header()->Out(), ((String*)ref)->Out()))?true:false;

  }
  
  bool EqualHeaderBSAndPrediction (TNode <BindingInfo>* bindingInfo, void* ref) {

    return (!strcmp(bindingInfo->Info()->ToStringHeader()->Out(), ((String*)ref)->Out()))?true:false;

  }
  
}  
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListBindingSitePrediction::ListBindingSitePrediction () {

  this->filenameCATH                          = new String ();
  this->filenamePatterns                      = new String ();
  this->filenameAnchorResidues                = new String ();
  this->filenameOut                           = new String ();

  this->fastaProfile                          = new ProcessCathFASTAProfile ();
  this->listPatterns                          = new Pratt2PatternsByCATH ();
  this->bindingProfile                        = new ProcessBindingFASTAProfile ();
  
  this->predictionsBS                         = new TListE <PredictBindingSiteByPattern> ();

  this->toString                              = new String ();

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListBindingSitePrediction::ListBindingSitePrediction (const ListBindingSitePrediction& listBindingSitePrediction) {

  this->filenameCATH                          = new String (listBindingSitePrediction.filenameCATH);
  this->filenamePatterns                      = new String (listBindingSitePrediction.filenamePatterns);
  this->filenameAnchorResidues                = new String (listBindingSitePrediction.filenameAnchorResidues);
  this->filenameOut                           = new String (listBindingSitePrediction.filenameOut);

  this->fastaProfile                          = new ProcessCathFASTAProfile (listBindingSitePrediction.fastaProfile);
  this->listPatterns                          = new Pratt2PatternsByCATH (listBindingSitePrediction.listPatterns);
  this->bindingProfile                        = new ProcessBindingFASTAProfile (listBindingSitePrediction.bindingProfile);
  
  this->predictionsBS                         = new TListE <PredictBindingSiteByPattern> (listBindingSitePrediction.predictionsBS);

  this->toString                              = new String (listBindingSitePrediction.toString);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListBindingSitePrediction::ListBindingSitePrediction (const ListBindingSitePrediction* listBindingSitePrediction) {

  this->filenameCATH                          = new String (listBindingSitePrediction->filenameCATH);
  this->filenamePatterns                      = new String (listBindingSitePrediction->filenamePatterns);
  this->filenameAnchorResidues                = new String (listBindingSitePrediction->filenameAnchorResidues);
  this->filenameOut                           = new String (listBindingSitePrediction->filenameOut);

  this->fastaProfile                          = new ProcessCathFASTAProfile (listBindingSitePrediction->fastaProfile);
  this->listPatterns                          = new Pratt2PatternsByCATH (listBindingSitePrediction->listPatterns);
  this->bindingProfile                        = new ProcessBindingFASTAProfile (listBindingSitePrediction->bindingProfile);
  
  this->predictionsBS                         = new TListE <PredictBindingSiteByPattern> (listBindingSitePrediction->predictionsBS);

  this->toString                              = new String (listBindingSitePrediction->toString);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListBindingSitePrediction::~ListBindingSitePrediction () {

  if (this->filenameCATH)           delete this->filenameCATH;
  if (this->filenamePatterns)       delete this->filenamePatterns;
  if (this->filenameAnchorResidues) delete this->filenameAnchorResidues;
  if (this->filenameOut)            delete this->filenameOut;

  if (this->fastaProfile)           delete this->fastaProfile;
  if (this->listPatterns)           delete this->listPatterns;
  if (this->bindingProfile)         delete this->bindingProfile;
  
  if (this->predictionsBS)          delete this->predictionsBS;

  if (this->toString)               delete this->toString;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListBindingSitePrediction::FilenameCATH (String* filenameCATH) {

  if (filenameCATH)
    *(this->filenameCATH) = *filenameCATH;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListBindingSitePrediction::FilenamePatterns (String* filenamePatterns) {

  if (filenamePatterns)
    *(this->filenamePatterns) = *filenamePatterns;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListBindingSitePrediction::FilenameAnchorResidues (String* filenameAnchorResidues) {

  if (filenameAnchorResidues)
    *(this->filenameAnchorResidues) = *filenameAnchorResidues;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListBindingSitePrediction::FilenameOut (String* filenameOut) {

  if (filenameOut)
    *(this->filenameOut) = *filenameOut;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListBindingSitePrediction::FastaProfile (ProcessCathFASTAProfile* fastaProfile) {

  if (fastaProfile)
    *(this->fastaProfile) = *fastaProfile;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListBindingSitePrediction::ListPatterns (Pratt2PatternsByCATH* listPatterns) {

  if (listPatterns)
    *(this->listPatterns) = *listPatterns;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListBindingSitePrediction::BindingProfile (ProcessBindingFASTAProfile* bindingProfile) {

  if (bindingProfile)
    *(this->bindingProfile) = *bindingProfile;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListBindingSitePrediction::PredictionsBS (TListE <PredictBindingSiteByPattern>* predictionsBS) {

  if (predictionsBS)
    *(this->predictionsBS) = *predictionsBS;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ListBindingSitePrediction::FilenameCATH (void) {

  return this->filenameCATH;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ListBindingSitePrediction::FilenamePatterns (void) {

  return this->filenamePatterns;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ListBindingSitePrediction::FilenameAnchorResidues (void) {

  return this->filenameAnchorResidues;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ListBindingSitePrediction::FilenameOut (void) {

  return this->filenameOut;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ProcessCathFASTAProfile* ListBindingSitePrediction::FastaProfile (void) {

  return this->fastaProfile;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
Pratt2PatternsByCATH* ListBindingSitePrediction::ListPatterns (void) {

  return this->listPatterns;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ProcessBindingFASTAProfile* ListBindingSitePrediction::BindingProfile (void) {

  return this->bindingProfile;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <PredictBindingSiteByPattern>* ListBindingSitePrediction::PredictionsBS (void) {

  return this->predictionsBS;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ListBindingSitePrediction::LoadData (void) {

  if (!this->filenameCATH           || !this->filenameCATH->Length()           || 
      !this->filenameAnchorResidues || !this->filenameAnchorResidues->Length())
    return false;
  
  this->fastaProfile->NamefileIn(this->filenameCATH);
  if (!this->fastaProfile->LoadData()) 
    return false;
  
  this->bindingProfile->FilenameBindingProfile(this->filenameAnchorResidues);
  if (!this->bindingProfile->LoadBindingProfile())
    return false;
  
  this->fastaProfile->ListCathDomainProfile()->SetInitial();
  while (this->fastaProfile->ListCathDomainProfile()->SetNext()) {
    
    PredictBindingSiteByPattern* newPredictBindingSiteByPattern = new PredictBindingSiteByPattern ();
    
    newPredictBindingSiteByPattern->Header(this->fastaProfile->ListCathDomainProfile()->GetCurrent()->ToStringHeader());
    newPredictBindingSiteByPattern->Sequence(this->fastaProfile->ListCathDomainProfile()->GetCurrent()->Sequence());
    
    newPredictBindingSiteByPattern->AllocateMemoryForScore(newPredictBindingSiteByPattern->Sequence()->Length());
    
    this->predictionsBS->Add(newPredictBindingSiteByPattern);
    
  }
  
  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ListBindingSitePrediction::PredictBindingSiteByType (String* type, float presicion, int scoreType) {

  if (!this->filenamePatterns || !this->filenamePatterns->Length())
    return false;

  this->listPatterns->Namefile(this->filenamePatterns);
  if (!this->listPatterns->LoadData())
    return false;

  if (!this->fastaProfile || !this->fastaProfile->ListCathDomainProfile()  || !this->fastaProfile->ListCathDomainProfile()->Length() || 
      !this->listPatterns || !this->listPatterns->ListGroupPrattPatterns() || !this->listPatterns->ListGroupPrattPatterns()->Length())
    return false;

  bool condCounterExtendedPatterns = false;
  long counterExtendedPatterns     = 0;

  this->fastaProfile->ListCathDomainProfile()->SetInitial();
  while (this->fastaProfile->ListCathDomainProfile()->SetNext()) {

    CathFASTAProfile*            currentCathFASTAProfile           = this->fastaProfile->ListCathDomainProfile()->GetCurrent();
    PredictBindingSiteByPattern* searchPredictBindingSiteByPattern = this->predictionsBS->FirstOcurrence(BindingSitePrediction::EqualHeader, currentCathFASTAProfile->ToStringHeader());

    if (!searchPredictBindingSiteByPattern) continue;

    String* sequence     = NULL;
    float*  scorePointer = NULL;

    if      (*(type) == "AA") { sequence = currentCathFASTAProfile->Sequence();              scorePointer = searchPredictBindingSiteByPattern->ScoreAA(); }
    else if (*(type) == "CH") { sequence = currentCathFASTAProfile->ResiduesClassChemical(); scorePointer = searchPredictBindingSiteByPattern->ScoreCH(); }
    else if (*(type) == "PH") { sequence = currentCathFASTAProfile->ResiduesClassPhysical(); scorePointer = searchPredictBindingSiteByPattern->ScorePH(); }
    else if (*(type) == "SS") { sequence = currentCathFASTAProfile->SecondaryStructureP();   scorePointer = searchPredictBindingSiteByPattern->ScoreSS(); }
    else if (*(type) == "MT") { sequence = currentCathFASTAProfile->ResiduesMT();            scorePointer = searchPredictBindingSiteByPattern->ScoreMT(); }

    this->listPatterns->ListGroupPrattPatterns()->SetInitial();
    while (this->listPatterns->ListGroupPrattPatterns()->SetNext()) {
      
      Pratt2Patterns* currentPratt2Patterns = this->listPatterns->ListGroupPrattPatterns()->GetCurrent();
      
      currentPratt2Patterns->Patterns()->SetInitial();
      while (currentPratt2Patterns->Patterns()->SetNext()) {
        
        PatternRecord*        currentPatternRecord = currentPratt2Patterns->Patterns()->GetCurrent();
        String*               pattern              = currentPatternRecord->Pattern();
        SearchPrositePattern* searchPrositePattern = new SearchPrositePattern ();
  
        searchPrositePattern->SearchPattern(sequence, pattern);    
        
        if (TYPE_PATTERN_COUNT == PATTERN_EXTENDED && !condCounterExtendedPatterns)
          counterExtendedPatterns += searchPrositePattern->ExtendedPattern()->Length();
        else if (TYPE_PATTERN_COUNT == PATTERN_COMPACT && !condCounterExtendedPatterns)
          counterExtendedPatterns++;
        
        searchPrositePattern->Segments()->SetInitial();
        searchPrositePattern->Positions()->SetInitial();
        while (searchPrositePattern->Segments()->SetNext() && searchPrositePattern->Positions()->SetNext())
          for (int i = *(searchPrositePattern->Positions()->GetCurrent()); 
                   i < (*(searchPrositePattern->Positions()->GetCurrent()) + searchPrositePattern->Segments()->GetCurrent()->Length()); 
                   i++) 
            (scorePointer[i])++;

      }
      
    }

    float maxValue = 0;

    for (long i = 0; i < searchPredictBindingSiteByPattern->Sequence()->Length(); i++)
      if (scorePointer[i] > maxValue)
        maxValue = scorePointer[i];

    for (long i = 0; i < searchPredictBindingSiteByPattern->Sequence()->Length(); i++) {
      if      (scoreType == SCORE_NORMAL)     scorePointer[i] = presicion * scorePointer[i] / ((counterExtendedPatterns)?counterExtendedPatterns:1);
      else if (scoreType == SCORE_CUMULATIVE) scorePointer[i] = presicion * scorePointer[i];
      else if (scoreType == SCORE_BINARY)     scorePointer[i] = (scorePointer[i])?1:0;
      else if (scoreType == SCORE_NORMALIZED) scorePointer[i] = presicion * scorePointer[i] / ((maxValue)?maxValue:1);
    }

    condCounterExtendedPatterns = true;

  }

  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ListBindingSitePrediction::PredictBindingSite (String* namefileAA, float presicionAA, 
                                                    String* namefileCH, float presicionCH, 
                                                    String* namefilePH, float presicionPH, 
                                                    String* namefileSS, float presicionSS, 
                                                    String* namefileMT, float presicionMT, 
                                                    int scoreType) {
  
  String type;
  int    considered = 0;

  if (namefileAA && *(namefileAA) != "NULL") {
    this->filenamePatterns->In(namefileAA);
    type.In("AA");
    if (!this->PredictBindingSiteByType(&type, presicionAA, scoreType))
      return false;
    considered++;
  }

  if (namefileCH && *(namefileCH) != "NULL") {
    this->filenamePatterns->In(namefileCH);
    type.In("CH");
    if (!this->PredictBindingSiteByType(&type, presicionCH, scoreType))
      return false;
    considered++;
  }

  if (namefilePH && *(namefilePH) != "NULL") {
    this->filenamePatterns->In(namefilePH);
    type.In("PH");
    if (!this->PredictBindingSiteByType(&type, presicionPH, scoreType))
      return false;
    considered++;
  }

  if (namefileSS && *(namefileSS) != "NULL") {
    this->filenamePatterns->In(namefileSS);
    type.In("SS");
    if (!this->PredictBindingSiteByType(&type, presicionSS, scoreType))
      return false;
    considered++;
  }

  if (namefileMT && *(namefileMT) != "NULL") {
    this->filenamePatterns->In(namefileMT);
    type.In("MT");
    if (!this->PredictBindingSiteByType(&type, presicionMT, scoreType))
      return false;
    considered++;
  }
  
  this->FillCumulativePredictionBindingSite(presicionAA, presicionCH, presicionPH, presicionSS, presicionMT, SCORE_NORMALIZED, considered, BY_PRODUCT);

  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ListBindingSitePrediction::PredictBindingSiteByTypeLengthWeighted (String* type, float presicion, int scoreType) {

  if (!this->filenamePatterns || !this->filenamePatterns->Length())
    return false;

  this->listPatterns->Namefile(this->filenamePatterns);
  if (!this->listPatterns->LoadData())
    return false;

  if (!this->fastaProfile || !this->fastaProfile->ListCathDomainProfile()  || !this->fastaProfile->ListCathDomainProfile()->Length() || 
      !this->listPatterns || !this->listPatterns->ListGroupPrattPatterns() || !this->listPatterns->ListGroupPrattPatterns()->Length())
    return false;

  bool condCounterExtendedPatterns = false;
  long counterExtendedPatterns     = 0;

  this->fastaProfile->ListCathDomainProfile()->SetInitial();
  while (this->fastaProfile->ListCathDomainProfile()->SetNext()) {

    CathFASTAProfile*            currentCathFASTAProfile           = this->fastaProfile->ListCathDomainProfile()->GetCurrent();
    PredictBindingSiteByPattern* searchPredictBindingSiteByPattern = this->predictionsBS->FirstOcurrence(BindingSitePrediction::EqualHeader, currentCathFASTAProfile->ToStringHeader());

    if (!searchPredictBindingSiteByPattern) continue;

    String* sequence     = NULL;
    float*  scorePointer = NULL;

    if      (*(type) == "AA") { sequence = currentCathFASTAProfile->Sequence();              scorePointer = searchPredictBindingSiteByPattern->ScoreAA(); }
    else if (*(type) == "CH") { sequence = currentCathFASTAProfile->ResiduesClassChemical(); scorePointer = searchPredictBindingSiteByPattern->ScoreCH(); }
    else if (*(type) == "PH") { sequence = currentCathFASTAProfile->ResiduesClassPhysical(); scorePointer = searchPredictBindingSiteByPattern->ScorePH(); }
    else if (*(type) == "SS") { sequence = currentCathFASTAProfile->SecondaryStructureP();   scorePointer = searchPredictBindingSiteByPattern->ScoreSS(); }
    else if (*(type) == "MT") { sequence = currentCathFASTAProfile->ResiduesMT();            scorePointer = searchPredictBindingSiteByPattern->ScoreMT(); }

    this->listPatterns->ListGroupPrattPatterns()->SetInitial();
    while (this->listPatterns->ListGroupPrattPatterns()->SetNext()) {
      
      Pratt2Patterns* currentPratt2Patterns = this->listPatterns->ListGroupPrattPatterns()->GetCurrent();
      
      currentPratt2Patterns->Patterns()->SetInitial();
      while (currentPratt2Patterns->Patterns()->SetNext()) {
        
        PatternRecord*        currentPatternRecord = currentPratt2Patterns->Patterns()->GetCurrent();
        String*               pattern              = currentPatternRecord->Pattern();
        SearchPrositePattern* searchPrositePattern = new SearchPrositePattern ();
  
        searchPrositePattern->SearchPattern(sequence, pattern);    
        
        if (TYPE_PATTERN_COUNT == PATTERN_EXTENDED && !condCounterExtendedPatterns)
          counterExtendedPatterns += searchPrositePattern->ExtendedPattern()->Length();
        else if (TYPE_PATTERN_COUNT == PATTERN_COMPACT && !condCounterExtendedPatterns)
          counterExtendedPatterns++;
        
        searchPrositePattern->Segments()->SetInitial();
        searchPrositePattern->Positions()->SetInitial();
        while (searchPrositePattern->Segments()->SetNext() && searchPrositePattern->Positions()->SetNext())
          for (int i = *(searchPrositePattern->Positions()->GetCurrent()); 
                   i < (*(searchPrositePattern->Positions()->GetCurrent()) + searchPrositePattern->Segments()->GetCurrent()->Length()); 
                   i++) 
            scorePointer[i] += pattern->Length();

      }
      
    }

    float maxValue = 0;

    for (long i = 0; i < searchPredictBindingSiteByPattern->Sequence()->Length(); i++)
      if (scorePointer[i] > maxValue)
        maxValue = scorePointer[i];

    for (long i = 0; i < searchPredictBindingSiteByPattern->Sequence()->Length(); i++) {
      if      (scoreType == SCORE_NORMAL)     scorePointer[i] = presicion * scorePointer[i] / ((counterExtendedPatterns)?counterExtendedPatterns:1);
      else if (scoreType == SCORE_CUMULATIVE) scorePointer[i] = presicion * scorePointer[i];
      else if (scoreType == SCORE_BINARY)     scorePointer[i] = (scorePointer[i])?1:0;
      else if (scoreType == SCORE_NORMALIZED) scorePointer[i] = presicion * scorePointer[i] / ((maxValue)?maxValue:1);
    }

    condCounterExtendedPatterns = true;

  }

  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ListBindingSitePrediction::PredictBindingSiteLengthWeighted (String* namefileAA, float presicionAA, 
                                                                  String* namefileCH, float presicionCH, 
                                                                  String* namefilePH, float presicionPH, 
                                                                  String* namefileSS, float presicionSS, 
                                                                  String* namefileMT, float presicionMT, 
                                                                  int scoreType) {
  
  String type;
  int    considered = 0;

  if (namefileAA && *(namefileAA) != "NULL") {
    this->filenamePatterns->In(namefileAA);
    type.In("AA");
    if (!this->PredictBindingSiteByTypeLengthWeighted(&type, presicionAA, scoreType))
      return false;
    considered++;
  }

  if (namefileCH && *(namefileCH) != "NULL") {
    this->filenamePatterns->In(namefileCH);
    type.In("CH");
    if (!this->PredictBindingSiteByTypeLengthWeighted(&type, presicionCH, scoreType))
      return false;
    considered++;
  }

  if (namefilePH && *(namefilePH) != "NULL") {
    this->filenamePatterns->In(namefilePH);
    type.In("PH");
    if (!this->PredictBindingSiteByTypeLengthWeighted(&type, presicionPH, scoreType))
      return false;
    considered++;
  }

  if (namefileSS && *(namefileSS) != "NULL") {
    this->filenamePatterns->In(namefileSS);
    type.In("SS");
    if (!this->PredictBindingSiteByTypeLengthWeighted(&type, presicionSS, scoreType))
      return false;
    considered++;
  }

  if (namefileMT && *(namefileMT) != "NULL") {
    this->filenamePatterns->In(namefileMT);
    type.In("MT");
    if (!this->PredictBindingSiteByTypeLengthWeighted(&type, presicionMT, scoreType))
      return false;
    considered++;
  }
  
  this->FillCumulativePredictionBindingSite(presicionAA, presicionCH, presicionPH, presicionSS, presicionMT, SCORE_NORMALIZED, considered, BY_PRODUCT);

  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ListBindingSitePrediction::FillAnchorPositions (void) {
  
  if (!this->bindingProfile || !this->bindingProfile->BindingProfiles() || !this->bindingProfile->BindingProfiles()->Length())
    return false;

  this->predictionsBS->SetInitial();
  while (this->predictionsBS->SetNext()) {

    PredictBindingSiteByPattern* currentPredictBindingSiteByPattern = this->predictionsBS->GetCurrent();
    
    BindingInfo* searchBindingInfo = this->bindingProfile->BindingProfiles()->FirstOcurrence(BindingSitePrediction::EqualHeaderBSAndPrediction, currentPredictBindingSiteByPattern->Header());

    if (!searchBindingInfo) continue;
    
    int positionSeq [currentPredictBindingSiteByPattern->Sequence()->Length()];
    int counter = 0;

    for (int i = 0; i < currentPredictBindingSiteByPattern->Sequence()->Length(); i++)
      currentPredictBindingSiteByPattern->AnchorResidues()[i] = 0;

    searchBindingInfo->Segments()->SetInitial();
    while (searchBindingInfo->Segments()->SetNext()) 
      for (int i = searchBindingInfo->Segments()->GetCurrent()->RangeStart(); i < searchBindingInfo->Segments()->GetCurrent()->RangeEnd(); i++)
        if (counter < currentPredictBindingSiteByPattern->Sequence()->Length()) 
          positionSeq[counter++] = i;

    searchBindingInfo->NearResiduesByLigand()->SetInitial();
    while (searchBindingInfo->NearResiduesByLigand()->SetNext()) {
      
      LigandNearResidues* currentLigandNearResidues = searchBindingInfo->NearResiduesByLigand()->GetCurrent();
      
      currentLigandNearResidues->NearResidues()->SetInitial();
      while (currentLigandNearResidues->NearResidues()->SetNext()) {
        
        String* currentNearResidue = currentLigandNearResidues->NearResidues()->GetCurrent();
        int     position           = atoi(currentNearResidue->Out() + 3);
        
        for (int i = 0; i < currentPredictBindingSiteByPattern->Sequence()->Length(); i++)
          if (positionSeq[i] == position)
            currentPredictBindingSiteByPattern->AnchorResidues()[i] = 1;
        
      }
      
    }

  }

  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ListBindingSitePrediction::FillCumulativePredictionBindingSite (float presicionAA, float presicionCH, float presicionPH, float presicionSS, float presicionMT, int scoreType, int considered, int type) {
  
  if (!this->predictionsBS || !this->predictionsBS->Length())
    return false;
  
  this->predictionsBS->SetInitial();
  while (this->predictionsBS->SetNext()) {
    
    PredictBindingSiteByPattern* currentPredictBindingSiteByPattern = this->predictionsBS->GetCurrent();
    float                        maxValue                           = 0;
    
    float internalPrescionAA = presicionAA;
    float internalPrescionCH = presicionCH;
    float internalPrescionPH = presicionPH;
    float internalPrescionSS = presicionSS;
    float internalPrescionMT = presicionMT;

    bool condAA = false;
    bool condCH = false;
    bool condPH = false;
    bool condSS = false;
    
    for (int i = 0; i < currentPredictBindingSiteByPattern->Sequence()->Length(); i++) {
      if (currentPredictBindingSiteByPattern->ScoreAA()[i] != 0) condAA = true;
      if (currentPredictBindingSiteByPattern->ScoreCH()[i] != 0) condCH = true;
      if (currentPredictBindingSiteByPattern->ScorePH()[i] != 0) condPH = true;
      if (currentPredictBindingSiteByPattern->ScoreSS()[i] != 0) condSS = true;
    }
    
    if (!condAA) internalPrescionAA = 0;
    if (!condCH) internalPrescionCH = 0;
    if (!condPH) internalPrescionPH = 0;
    if (!condSS) internalPrescionSS = 0;
    
    if (!internalPrescionAA && !internalPrescionCH && !internalPrescionPH && !internalPrescionSS)
      continue;
    
    for (int i = 0; i < currentPredictBindingSiteByPattern->Sequence()->Length(); i++) {
      
      if (type == BY_SUM) {
        
        currentPredictBindingSiteByPattern->ScoreCumul()[i]  = currentPredictBindingSiteByPattern->ScoreAA()[i] 
                                                             + currentPredictBindingSiteByPattern->ScoreCH()[i]
                                                             + currentPredictBindingSiteByPattern->ScorePH()[i]
                                                             + currentPredictBindingSiteByPattern->ScoreSS()[i]
                                                             + currentPredictBindingSiteByPattern->ScoreMT()[i];

        currentPredictBindingSiteByPattern->ScoreCumul()[i] /= ((considered)?considered:1);

      }
      else if (type == BY_PRODUCT) {
        
        currentPredictBindingSiteByPattern->ScoreCumul()[i]  = ((internalPrescionAA)?currentPredictBindingSiteByPattern->ScoreAA()[i]:1)
                                                             * ((internalPrescionCH)?currentPredictBindingSiteByPattern->ScoreCH()[i]:1)
                                                             * ((internalPrescionPH)?currentPredictBindingSiteByPattern->ScorePH()[i]:1)
                                                             * ((internalPrescionSS)?currentPredictBindingSiteByPattern->ScoreSS()[i]:1);

        
      }
      
      if (currentPredictBindingSiteByPattern->ScoreCumul()[i] > maxValue)
        maxValue = currentPredictBindingSiteByPattern->ScoreCumul()[i];
        
    }

    if (scoreType == SCORE_NORMALIZED)
      for (int i = 0; i < currentPredictBindingSiteByPattern->Sequence()->Length(); i++)
        currentPredictBindingSiteByPattern->ScoreCumul()[i] /= ((maxValue)?maxValue:1);
    
  }
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ListBindingSitePrediction::ToStringScores (void) {

  int type = 0;
  
  this->toString->In("");
  
  this->predictionsBS->SetInitial();
  while (this->predictionsBS->SetNext()) {
    
    PredictBindingSiteByPattern* currentPredictBindingSiteByPattern = this->predictionsBS->GetCurrent();
    
    this->toString->Add(currentPredictBindingSiteByPattern->Header());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->Sequence(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->ScoreAA(),        currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->ScoreCH(),        currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->ScorePH(),        currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->ScoreSS(),        currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->ScoreMT(),        currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->ScoreCumul(),     currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->AnchorResidues(), currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    
  }
  
  return this->toString;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ListBindingSitePrediction::ToCSVScores (void) {

  int type = 1;
  
  this->toString->In("");
  
  this->predictionsBS->SetInitial();
  while (this->predictionsBS->SetNext()) {
    
    PredictBindingSiteByPattern* currentPredictBindingSiteByPattern = this->predictionsBS->GetCurrent();
    
    this->toString->Add(currentPredictBindingSiteByPattern->Header());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->Sequence(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->ScoreAA(),        currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->ScoreCH(),        currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->ScorePH(),        currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->ScoreSS(),        currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->ScoreMT(),        currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->ScoreCumul(),     currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    this->toString->Add(this->OutFormatedArray(currentPredictBindingSiteByPattern->AnchorResidues(), currentPredictBindingSiteByPattern->Sequence()->Length(), type).Out());
    this->toString->Add("\n");
    
  }
  
  return this->toString;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String ListBindingSitePrediction::OutFormatedArray (String* data, int type) {
  
  String out;
  char   buffer [MAX_SIZE];
  
  out.In("");
  if (data)
    for (long i = 0; i < data->Length(); i++) {
      if (!type) sprintf(buffer, "%c      \0", data->Out()[i]);
      else       sprintf(buffer, (!i)?"%c\0":";%c\0", data->Out()[i]);
      out.Add(buffer);
    }
    
  return out;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String ListBindingSitePrediction::OutFormatedArray (float* data, int size, int type) {
  
  String out;
  char   buffer [MAX_SIZE];
  
  out.In("");
  if (data)
    for (long i = 0; i < size; i++) {
      if (!type) sprintf(buffer, "%3.2f \0", data[i]);
      else       sprintf(buffer, (!i)?"%3.2f\0":";%3.2f\0", data[i]);
      out.Add(buffer);
    }
    
  return out;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ListBindingSitePrediction::OutToFile (void) {

  if (!this->filenameOut || !this->filenameOut->Length())
    return false;
  
  ofstream file (this->filenameOut->Out());
  if (!file.is_open())
    return false;
  file << this->ToStringScores()->Out();
  file.close();
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ListBindingSitePrediction::OutToCSVFile (void) {

  if (!this->filenameOut || !this->filenameOut->Length())
    return false;
  
  ofstream file (this->filenameOut->Out());
  if (!file.is_open())
    return false;
  file << this->ToCSVScores()->Out();
  file.close();
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListBindingSitePrediction ListBindingSitePrediction::operator= (const ListBindingSitePrediction& listBindingSitePrediction) {

  *(this->filenameCATH)           = *(listBindingSitePrediction.filenameCATH);
  *(this->filenamePatterns)       = *(listBindingSitePrediction.filenamePatterns);
  *(this->filenameAnchorResidues) = *(listBindingSitePrediction.filenameAnchorResidues);
  *(this->filenameOut)            = *(listBindingSitePrediction.filenameOut);

  *(this->fastaProfile)           = *(listBindingSitePrediction.fastaProfile);
  *(this->listPatterns)           = *(listBindingSitePrediction.listPatterns);
  *(this->bindingProfile)         = *(listBindingSitePrediction.bindingProfile);
  
  *(this->predictionsBS)          = *(listBindingSitePrediction.predictionsBS);

  *(this->toString)               = *(listBindingSitePrediction.toString);

  return *this;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
